<template>
  <div>
    <template v-for="(value, key) in data" :key="key">
      <a-card
        v-if="!isObject(value) && !Array.isArray(value)"
        size="small"
        style="margin-bottom: 12px"
      >
        <div style="display: flex; align-items: center">
          <span class="key-label">{{ key }}</span>
          <a-input
            v-if="!activeTextareas[key]"
          :value="String(value)"
            style="flex: 1; margin-left: 8px"
            @click="() => activateTextarea(key)"
            readonly
        />
          <a-textarea
        v-else
            :value="String(value)"
            style="flex: 1; margin-left: 8px"
            @change="(e) => updateValue(key, e.target.value)"
            @blur="() => deactivateTextarea(key)"
            :auto-size="{ minRows: 1, maxRows: 6 }"
          />
          <a-switch
            v-if="typeof value === 'boolean'"
            :checked="value"
            @change="(checked) => updateValue(key, checked)"
            style="margin-left: 8px"
          />
        </div>
      </a-card>

      <a-card
        v-else-if="Array.isArray(value)"
        :title="key"
        size="small"
        style="margin-bottom: 12px"
    >
        <template #extra>
          <a-button type="link" @click="toggleExpand(key)">
            {{ isExpanded(key) ? '收起' : '展开' }}
          </a-button>
</template>
        <div v-if="isExpanded(key)">
          <div v-for="(item, index) in value" :key="index" style="display: flex; margin-bottom: 8px">
            <json-editor
              :data="{ [index]: item }"
              @update:data="(newData) => updateArrayItem(key, index, newData[index])"
            />
            <a-button
              type="link"
              danger
              @click="removeArrayItem(key, index)"
            >
              删除
            </a-button>
          </div>
          <a-button
            type="dashed"
            @click="showAddArrayItemModal(key)"
          >
            添加项目
          </a-button>
        </div>
      </a-card>

      <a-card
        v-else
        :title="key"
        size="small"
        style="margin-bottom: 12px"
      >
        <template #extra>
          <a-button type="link" @click="toggleExpand(key)">
            {{ isExpanded(key) ? '收起' : '展开' }}
          </a-button>
        </template>
        <div v-if="isExpanded(key)">
          <json-editor
            :data="value"
            @update:data="(newData) => updateObject(key, newData)"
          />
          <a-button
            type="dashed"
            @click="showAddPropertyModal(key)"
            style="margin-top: 8px"
          >
            添加属性
          </a-button>
        </div>
      </a-card>
    </template>

    <a-modal
      v-model:visible="addPropertyModal.visible"
      :title="addPropertyModal.title"
      @ok="handleAddProperty"
      @cancel="cancelAddProperty"
    >
      <a-form layout="vertical">
        <a-form-item label="属性名">
          <a-input v-model:value="addPropertyModal.key" />
        </a-form-item>
        <a-form-item label="属性值">
          <a-input v-model:value="addPropertyModal.value" />
        </a-form-item>
      </a-form>
    </a-modal>

    <a-modal
      v-model:visible="addArrayItemModal.visible"
      title="添加数组项"
      @ok="handleAddArrayItem"
      @cancel="cancelAddArrayItem"
    >
      <a-form layout="vertical">
        <a-form-item label="项值">
          <a-input v-model:value="addArrayItemModal.value" />
        </a-form-item>
      </a-form>
    </a-modal>
  </div>
</template>

<script>
import { ref } from 'vue'

export default {
  name: 'JsonEditor',
  props: {
    data: {
      type: Object,
      required: true
    }
  },
  setup() {
    const expandedKeys = ref(new Set())
    const activeTextareas = ref({})
    const addPropertyModal = ref({
        visible: false,
        key: '',
        value: '',
        targetKey: null,
        title: '添加新属性'
    })
    const addArrayItemModal = ref({
        visible: false,
        value: '',
        targetKey: null
    })

    const activateTextarea = (key) => {
      activeTextareas.value[key] = true
    }

    const deactivateTextarea = (key) => {
      activeTextareas.value[key] = false
    }

    return {
      expandedKeys,
      activeTextareas,
      addPropertyModal,
      addArrayItemModal,
      activateTextarea,
      deactivateTextarea
    }
    },
  methods: {
    isObject(val) {
      return typeof val === 'object' && val !== null && !Array.isArray(val)
    },
    isExpanded(key) {
      return this.expandedKeys.has(key)
    },
    toggleExpand(key) {
      if (this.expandedKeys.has(key)) {
        this.expandedKeys.delete(key)
      } else {
        this.expandedKeys.add(key)
      }
    },
    showAddPropertyModal(key) {
      this.addPropertyModal = {
        visible: true,
        key: 'newProperty',
        value: '',
        targetKey: key,
        title: `为 ${key} 添加新属性`
      }
    },
    showAddArrayItemModal(key) {
      this.addArrayItemModal = {
        visible: true,
        value: '',
        targetKey: key
      }
    },
    handleAddProperty() {
      if (!this.addPropertyModal.key) return

      const newObj = {
        ...this.data[this.addPropertyModal.targetKey],
        [this.addPropertyModal.key]: this.addPropertyModal.value
      }
      const newData = {
        ...this.data,
        [this.addPropertyModal.targetKey]: newObj
      }
      this.$emit('update:data', newData)
      this.cancelAddProperty()
    },
    handleAddArrayItem() {
      const newArray = [
        ...this.data[this.addArrayItemModal.targetKey],
        this.addArrayItemModal.value
      ]
      const newData = {
        ...this.data,
        [this.addArrayItemModal.targetKey]: newArray
      }
      this.$emit('update:data', newData)
      this.cancelAddArrayItem()
    },
    cancelAddProperty() {
      this.addPropertyModal = {
        visible: false,
        key: '',
        value: '',
        targetKey: null,
        title: '添加新属性'
      }
    },
    cancelAddArrayItem() {
      this.addArrayItemModal = {
        visible: false,
        value: '',
        targetKey: null
      }
    },
    updateValue(key, value) {
      this.$emit('update:data', {
        ...this.data,
        [key]: value
      })
    },
    updateArrayItem(arrayKey, index, value) {
      const newArray = [...this.data[arrayKey]]
      newArray[index] = value
      this.$emit('update:data', {
        ...this.data,
        [arrayKey]: newArray
      })
    },
    updateObject(key, newData) {
      this.$emit('update:data', {
        ...this.data,
        [key]: newData
      })
    },
    removeArrayItem(key, index) {
      const newArray = [...this.data[key]]
      newArray.splice(index, 1)
      this.$emit('update:data', {
        ...this.data,
        [key]: newArray
      })
  }
}
}
</script>

<style scoped>
.key-label {
  min-width: 100px;
  padding: 0 8px;
  font-weight: bold;
}
</style>

